package com.aptemo.webetek.server.data;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.jdo.annotations.Element;
import javax.jdo.annotations.Extension;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.aptemo.webetek.client.enums.EnumUserRole;
import com.aptemo.webetek.client.enums.EnumUserStatus;
import com.aptemo.webetek.shared.UserBean;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.gwt.user.client.rpc.IsSerializable;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class WebetekUser implements IsSerializable
{

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key				key;

	// @Persistent
	// private UserGroup team;
	@Persistent
	@Extension(vendorName = "datanucleus", key = "gae.parent-pk", value = "true")
	private Key				parentKey;

	// owned 1:N unidirectional relationship - WebetekUser : Stake
	@Persistent
	@Element(dependent = "true")
	private List<Stake>		stakes		= new ArrayList<Stake>();

	@Persistent
	@Element(dependent = "true")
	private List<Payment>	payments	= new ArrayList<Payment>();

	@Persistent
	private String			email;

	@Persistent
	private EnumUserRole	role		= EnumUserRole.GAMER;

	@Persistent
	private EnumUserStatus	status		= EnumUserStatus.CREATED;

	@Persistent
	private double			balance		= 0.0;

	@Persistent
	private double			limit		= 0.0;

	@Persistent
	private Date			created;

	// fields that simplify the rankings and statistics calculations (could be
	// updated asynch)...

	// = sum all closed stake.earnings
	@Persistent
	private Double			earnings	= 0.0;

	@Persistent
	private Double			investment	= 0.0;

	// = count all stake bets
	@Persistent
	private Integer			totalBetCnt	= 0;

	// = count won stake bets
	@Persistent
	private Integer			wonBetCnt	= 0;

	private String			sid;

	public WebetekUser(String email)
	{
		this.setEmail(email);

		this.created = new Date();
	}

	public void setRole(EnumUserRole arole)
	{
		this.role = arole;
	}

	public EnumUserRole getRole()
	{
		return role;
	}

	public void setEmail(String email)
	{
		this.email = email;
	}

	public String getEmail()
	{
		return email;
	}

	public void setStatus(EnumUserStatus status)
	{
		this.status = status;
	}

	public EnumUserStatus getStatus()
	{
		return status;
	}

	public void setKey(Key key)
	{
		this.key = key;
	}

	public Key getKey()
	{
		return key;
	}

	//
	// public void setStakes(List<Stake> stakes)
	// {
	// this.stakes = stakes;
	// }

	public List<Stake> getStakes()
	{
		return stakes;
	}

	public void addStake(Stake stake)
	{
		stakes.add(stake);
	}

	public String getSid()
	{
		if (sid == null)
		{
			this.sid = KeyFactory.keyToString(key);
		}
		return sid;
	}

	private void setBalance(double balance)
	{
		DecimalFormat twoDForm = new DecimalFormat("#.##");
		this.balance = Double.valueOf(twoDForm.format(balance));
	}

	public double getBalance()
	{
		return balance;
	}

	public void setLimit(double limit)
	{
		this.limit = limit;
	}

	public double getLimit()
	{
		return limit;
	}

	// public UserGroup getParent()
	// {
	// return parent;
	// }

	public Date getCreated()
	{
		return created;
	}

	public void addPayment(Payment payment)
	{
		// do the calculation...
		double curBalance = getBalance();
		setBalance(curBalance + payment.getAmount());

		// update earnings..
		switch (payment.getType())
		{
			case EARNINGS:
			case STORNO:
				earnings = getEarnings();
				earnings += payment.getAmount();
				break;
			case BET:
				investment = getInvestment();
				investment += payment.getAmount();
				break;
		}

		payments.add(payment);
	}

	public List<Payment> getPayments()
	{
		return payments;
	}

	// public Double getEarnings()
	// {
	// Double earnings = 0.0;
	// for (Stake stake : stakes)
	// {
	// if (stake.getStatus() == EnumStakeStatus.CLOSED)
	// {
	// earnings += stake.getEarnings();
	// }
	// }
	// return earnings;
	// }

	public Double getEarnings()
	{
		if (earnings == null)
		{
			return 0.0;
		}
		return earnings;
	}

	public UserBean toBean()
	{
		UserBean bean = new UserBean(getEmail());

		bean.setEmail(email);
		bean.setRole(role);
		bean.setKey(getSid());
		bean.setBalance(balance);
		bean.setStatus(status);

		bean.setTotalBetCnt(getTotalBetCnt());
		bean.setWonBetCnt(getWonBetCnt());
		bean.setEarnings(getEarnings());
		bean.setInvestment(getInvestment());
		// ArrayList<StakeBean> stakelist = new ArrayList<StakeBean>();
		// for (Stake item : stakes)
		// {
		// StakeBean stake = item.toBean();
		// stakelist.add(stake);
		// }
		// bean.setStakes(stakelist);

		return bean;
	}

	// public UserGroup getParent()
	// {
	// return team; // pm.getObjectById(UserGroup.class, key.getParent());
	// }

	public void updateWonBetsCount(int wonCnt)
	{
		wonBetCnt = getWonBetCnt() + wonCnt;
	}

	public void updateAllBetCount(int totalCnt)
	{
		totalBetCnt = getTotalBetCnt() + totalCnt;

	}

	public Integer getTotalBetCnt()
	{
		if (totalBetCnt == null)
		{
			return 0;
		}
		return totalBetCnt;
	}

	public Integer getWonBetCnt()
	{
		if (wonBetCnt == null)
		{
			return 0;
		}
		return wonBetCnt;
	}

	public Double getInvestment()
	{
		if (investment == null)
		{
			return 0.0;
		}
		return investment;
	}

	public void resetBetCounters()
	{
		wonBetCnt = 0;
		totalBetCnt = 0;
	}

	public void setInvestment(Double investment)
	{
		if (this.investment != investment)
		{
			// TODO warning...
			this.investment = investment;
		}
	}

	public void setEarnings(double earnings)
	{
		if (this.earnings != earnings)
		{
			// TODO warning...
			this.earnings = earnings;
		}
	}

}
